package com.tbit.main.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.tbit.main.constant.DaoParamConstant;
import com.tbit.main.constant.MachineAbnormalConstant;
import com.tbit.main.constant.MachineStateConstant;
import com.tbit.main.constant.UserConstant;
import com.tbit.main.dao.core.RideLogDao;
import com.tbit.main.dao.core.UserDao;
import com.tbit.main.dao.data.WeatherHistoryDao;
import com.tbit.main.dao.log.DispatchLogDao;
import com.tbit.main.dao.log.MoveLogDao;
import com.tbit.main.dao.log.PowerChangeLogDao;
import com.tbit.main.dao.stat.*;
import com.tbit.main.pojo.*;
import com.tbit.main.service.*;
import com.tbit.main.util.DateTimeUtil;
import com.tbit.main.util.LogUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author LMY
 * @create 2021-01-05 21:24
 * 预统计定时任务
 */
@Service("operationReportsService")
public class OperationReportsServiceImpl implements OperationReportsService {
    private static List<Integer> detects = null;
    private static List<Account> accounts = null;

    private static List<Integer> regionId = null;

    @Autowired
    private AccountService accountService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private MachineService machineService;
    @Autowired
    private MachineAbnormalService machineAbnormalService;
    @Autowired
    private MachineFaultService machineFaultService;
    @Autowired
    private MachineDayStaService machineDayStaService;
    @Autowired
    private MachineStatusService machineStatusService;
    @Autowired
    private AccountConfigService accountConfigService;
    @Autowired
    private DispatchDayStaDao dispatchDayStaDao;
    @Autowired
    private DispatchLogDao dispatchLogDao;
    @Autowired
    private MoveDayStaDao moveDayStaDao;
    @Autowired
    private MoveLogDao moveLogDao;
    @Autowired
    private PowerDayStaDao powerDayStaDao;
    @Autowired
    private PowerChangeLogDao powerChangeLogDao;
    @Autowired
    private NewUserDayStaDao newUserDayStaDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private MachineBorrowService machineBorrowService;
    @Autowired
    private OperationHourStaDao operationHourStaDao;
    @Autowired
    private MachineDayStaDao machineDayStaDao;
    @Autowired
    private RideLogDao rideLogDao;
    @Autowired
    private WeatherHistoryDao weatherHistoryDao;
    @Autowired
    private GeoreGionService georeGionService;
    @Autowired
    private GeoreMachineService georeMachineService;
    @Autowired
    private AccountUserService accountUserService;

    /**
     * 运营分析日统计
     */
    @Override
    //@Scheduled(cron = "0 30 2 * * ?")
    public void operationDayCount() {
        LogUtil.info("运营分析日统计，定时任务");
        long t1 = System.currentTimeMillis();
        List<AccountConfig> accountConfigList = new LinkedList<>();
        Map<String, Object> params = new HashMap<>();
        String toDay = DateTimeUtil.getNowTimeYMD();

        if (null == detects || detects.size() == 0) {
            //获取所有的运营区域
            accounts = accountService.getByType(UserConstant.ACCOUNT_AGENT);
        }
        if (null != accounts) {
            detects = accounts.stream().map(Account::getAccountId).collect(Collectors.toList());
            //获取运营区域配置
            accountConfigList = accountConfigService.getByListAccountId(detects);
        }
        if (null == detects) {
            return;
        }

        /**运维人员*/
        Map<Integer, Integer> accountBoundCounts = new HashMap<>();
        /**区域人员*/
        if (accountConfigList != null && accountConfigList.size() > 0) {
            List<Integer> accountIds = accountConfigList.stream().map(AccountConfig::getAccountId).collect(Collectors.toList());
            List<Integer> subroleType = new LinkedList<>();
            subroleType.add(1);
            subroleType.add(2);
            List<Map<String, Object>> accountBoundCountDB = accountUserService.getByAccountIdAndType(accountIds, subroleType, DateTimeUtil.getNowTimeYMD());

            for (int i = 0; i < accountBoundCountDB.size(); i++) {
                accountBoundCounts.put(Integer.parseInt(accountBoundCountDB.get(i).get("accountId").toString()), Integer.parseInt(accountBoundCountDB.get(i).get("accountUserCount").toString()));
            }

        }

        for (AccountConfig account : accountConfigList) {

            /**删除前一天的key*/
            if (redisService.get(DateTimeUtil.getDayAgo() + ".MAIN" + account.getAccountId()) != null) {
                redisService.del(DateTimeUtil.getDayAgo() + ".MAIN" + account.getAccountId());
            }

            params.put(DaoParamConstant.accountId, account.getAccountId());
            params.put("isCount", DateTimeUtil.getEndDateTimeBefore(-1));
            /***获取昨天的开始时间*/
            params.put("startDt", DateTimeUtil.getNowDateTimeBefore(-1) + " 00:00:00");
            /**获取今天的开始时间*/
            params.put("endDt", DateTimeUtil.getNowDateTimeBefore(0) + " 00:00:00");
            /**
             * 按天统计调度
             */
            List<DispatchDaySta> dispatchDayStaList = dispatchDayStaDao.getByAccountIdDateDay(params);
            if (dispatchDayStaList == null || dispatchDayStaList.size() == 0) {
                /**不存在数据即从按天统计到昨天*/
                List<Map<String, Object>> dispatchLogList = dispatchLogDao.getGroupByDay(params);
                if (!dispatchLogList.isEmpty()) {
                    for (Map<String, Object> map : dispatchLogList) {
                        Integer userCount = accountBoundCounts.get(account.getAccountId());
                        if (userCount == null || userCount == 0) {
                            map.put("meanDispatchCount", 0.00);
                        } else {
                            /**计算平均调度*/
                            BigDecimal b = new BigDecimal((float) Integer.parseInt(map.get("dispatchCount").toString()) / userCount);
                            Double result = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                            map.put("meanDispatchCount", result);
                        }
                    }

                    dispatchDayStaDao.insertBatch(dispatchLogList);
                }
                redisService.incr(String.valueOf(account.getAccountId()));
            } else {
                /**有数据则只计算前一天*/
                DispatchDaySta dispatchDaySta = dispatchDayStaList.get(0);
                if (!dispatchDaySta.getAddTime().substring(0, 10).equals(toDay)) {
                    Map<String, Object> maps = dispatchLogDao.statYesterdayOrder(params);
                    if (Integer.parseInt(maps.get("dispatchCount").toString()) != 0) {
                        LogUtil.info("accountId:" + account.getAccountId() + "调度统计一天");

                        Integer userCount = accountBoundCounts.get(account.getAccountId());
                        if (userCount == null || userCount == 0) {
                            maps.put("meanDispatchCount", 0.00);
                        } else {
                            /**计算平均调度*/
                            BigDecimal b = new BigDecimal((float) Integer.parseInt(maps.get("dispatchCount").toString()) / userCount);
                            Double result = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                            maps.put("meanDispatchCount", result);
                        }

                        dispatchDayStaDao.insertByMap(maps);
                    }
                    dispatchDayStaDao.update(account.getAccountId());

                    redisService.incr(String.valueOf(account.getAccountId()));
                }
            }

            /**
             * 按天统计挪车*/

            List<MoveDaySta> moveDayStaList = moveDayStaDao.getByAccountIdDateDay(params);
            if (moveDayStaList == null || moveDayStaList.size() == 0) {
                /**不存在数据即从按天统计到昨天*/
                List<Map<String, Object>> moveLogList = moveLogDao.getGroupByDay(params);
                if (!moveLogList.isEmpty()) {
                    LogUtil.info("accountId:" + account.getAccountId() + "挪车统计所有");

                    for (Map<String, Object> map : moveLogList) {
                        Integer userCount = accountBoundCounts.get(account.getAccountId());
                        if (userCount == null || userCount == 0) {
                            map.put("meanMoveCount", 0.00);
                        } else {
                            /**计算平均挪车*/
                            BigDecimal b = new BigDecimal((float) Integer.parseInt(map.get("moveCount").toString()) / userCount);
                            Double result = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                            map.put("meanMoveCount", result);
                        }
                    }


                    moveDayStaDao.insertBatch(moveLogList);
                }
                redisService.incr(String.valueOf(account.getAccountId()));
            } else {
                /* *有数据则只计算前一天*/
                MoveDaySta moveDaySta = moveDayStaList.get(0);
                if (!moveDaySta.getAddTime().substring(0, 10).equals(toDay)) {
                    Map<String, Object> maps = moveLogDao.statYesterdayOrder(params);
                    if (Integer.parseInt(maps.get("moveCount").toString()) != 0) {
                        LogUtil.info("accountId:" + account.getAccountId() + "挪车统计一天");

                        Integer userCount = accountBoundCounts.get(account.getAccountId());
                        if (userCount == null || userCount == 0) {
                            maps.put("meanMoveCount", 0.00);
                        } else {
                            /**计算平均挪车*/
                            BigDecimal b = new BigDecimal((float) Integer.parseInt(maps.get("moveCount").toString()) / userCount);
                            Double result = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                            maps.put("meanMoveCount", result);
                        }

                        moveDayStaDao.insertByMap(maps);
                    }
                    moveDayStaDao.update(account.getAccountId());
                    redisService.incr(String.valueOf(account.getAccountId()));
                }
            }

            /**
             * 按天统计换电*/

            List<PowerDaySta> powerDayStaList = powerDayStaDao.getByAccountIdDateDay(params);
            if (powerDayStaList == null || powerDayStaList.size() == 0) {
                /**不存在数据即从按天统计到昨天*/
                List<Map<String, Object>> powerLogList = powerChangeLogDao.getGroupByDay(params);
                if (!powerLogList.isEmpty()) {
                    LogUtil.info("accountId:" + account.getAccountId() + "换电统计所有");

                    for (Map<String, Object> map : powerLogList) {
                        Integer userCount = accountBoundCounts.get(account.getAccountId());
                        if (userCount == null || userCount == 0) {
                            map.put("meanPowerCount", 0.00);
                        } else {
                            /**计算平均换电*/
                            BigDecimal b = new BigDecimal((float) Integer.parseInt(map.get("powerCount").toString()) / userCount);
                            Double result = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                            map.put("meanPowerCount", result);
                        }
                    }


                    powerDayStaDao.insertBatch(powerLogList);
                }
                redisService.incr(String.valueOf(account.getAccountId()));
            } else {
                /**有数据则只计算前一天*/
                PowerDaySta powerDaySta = powerDayStaList.get(0);
                if (!powerDaySta.getAddTime().substring(0, 10).equals(toDay)) {
                    Map<String, Object> maps = powerChangeLogDao.statYesterdayOrder(params);
                    if (Integer.parseInt(maps.get("powerCount").toString()) != 0) {
                        LogUtil.info("accountId:" + account.getAccountId() + "换电统计一天");

                        Integer userCount = accountBoundCounts.get(account.getAccountId());
                        if (userCount == null || userCount == 0) {
                            maps.put("meanPowerCount", 0.00);
                        } else {
                            /**计算平均换电*/
                            BigDecimal b = new BigDecimal((float) Integer.parseInt(maps.get("powerCount").toString()) / userCount);
                            Double result = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                            maps.put("meanPowerCount", result);
                        }

                        powerDayStaDao.insertByMap(maps);
                    }
                    powerDayStaDao.update(account.getAccountId());
                    redisService.incr(String.valueOf(account.getAccountId()));
                }
            }

            /**
             * 按天统计新增用户/公里数/最高天气*/
            List<NewUserDaySta> newUserDayStaList = newUserDayStaDao.getByAccountIdDateDay(params);
            if (newUserDayStaList == null || newUserDayStaList.size() == 0) {
                /**不存在数据即从按天统计到昨天*/
                List<Map<String, Object>> newUserList = userDao.getGroupByDay(params);
                List<Map<String, Object>> newMileageList = rideLogDao.getGroupByDay(params);
                List<Map<String, Object>> newWeatherList = weatherHistoryDao.getGroupByDay(params);

                Set<String> dateSet = new HashSet<>();

                Map<String, Map<String, Object>> userMap = new HashMap<>();
                for (Map<String, Object> newMap : newUserList) {
                    userMap.put(newMap.get("accountId").toString() + newMap.get("newUserDayDate"), newMap);
                    dateSet.add(newMap.get("accountId").toString() + newMap.get("newUserDayDate"));
                }

                Map<String, Map<String, Object>> mileageMap = new HashMap<>();
                for (Map<String, Object> newMap : newMileageList) {
                    mileageMap.put(newMap.get("accountId").toString() + newMap.get("newMileageDayDate"), newMap);
                    dateSet.add(newMap.get("accountId").toString() + newMap.get("newMileageDayDate"));
                }

                Map<String, Map<String, Object>> weatherMap = new HashMap<>();
                for (Map<String, Object> newMap : newWeatherList) {
                    weatherMap.put(newMap.get("accountId").toString() + newMap.get("weaterDayDate"), newMap);
                    dateSet.add(newMap.get("accountId").toString() + newMap.get("weaterDayDate"));
                }

                List<Map<String, Object>> mapList = new ArrayList<>();
                for (String key : dateSet) {
                    Map<String, Object> map = new HashMap<>();
                    if (mileageMap.containsKey(key)) {
                        map.put("newMileageCount", mileageMap.get(key).get("newMileageCount"));
                        map.put(DaoParamConstant.accountId, mileageMap.get(key).get("accountId"));
                        map.put("dataTime", mileageMap.get(key).get("newMileageDayDate"));
                    } else {
                        map.put("newMileageCount", 0);
                    }
                    if (userMap.containsKey(key)) {
                        map.put("newUserCount", userMap.get(key).get("newUserCount"));
                        map.put(DaoParamConstant.accountId, userMap.get(key).get("accountId"));
                        map.put("dataTime", userMap.get(key).get("newUserDayDate"));
                    } else {
                        map.put("newUserCount", 0);
                    }
                    if (weatherMap.containsKey(key)) {
                        map.put("newWeatherCount", weatherMap.get(key).get("newWeatherCount"));
                        map.put(DaoParamConstant.accountId, weatherMap.get(key).get("accountId"));
                        map.put("dataTime", weatherMap.get(key).get("weaterDayDate"));
                    } else {
                        map.put("newWeatherCount", 0);
                    }
                    if (!map.isEmpty()) {
                        mapList.add(map);
                    }
                }

                if (!mapList.isEmpty()) {
                    LogUtil.info("accountId:" + account.getAccountId() + "新用户,新里程,新气温 统计所有");
                    newUserDayStaDao.insertBatch(mapList);
                }
                redisService.incr(String.valueOf(account.getAccountId()));
            } else {
                /* *有数据则只计算前一天*/
                NewUserDaySta newUserDaySta = newUserDayStaList.get(0);
                if (!newUserDaySta.getAddTime().substring(0, 10).equals(toDay)) {
                    Map<String, Object> userMaps = userDao.statYesterdayOrder(params);
                    Map<String, Object> mileageMaps = rideLogDao.statYesterdayOrder(params);
                    Map<String, Object> weatherMaps = weatherHistoryDao.statYesterdayOrder(params);

                    Map<String, Object> map = new HashMap<>();

                    Set<String> strings = new HashSet<>();
                    strings.add(userMaps.get("accountId").toString());
                    strings.add(mileageMaps.get("accountId").toString());
                    strings.add(weatherMaps.get("accountId").toString());

                    for (String key : strings) {
                        map.put(DaoParamConstant.accountId, key);
                        map.put("newMileageDayDate", mileageMaps.get("newMileageDayDate"));

                        map.put("newMileageCount", mileageMaps.get("newMileageCount"));
                        map.put("newUserCount", userMaps.get("newUserCount"));
                        if (weatherMaps.containsKey("newWeatherCount")) {
                            if (weatherMaps.get("newWeatherCount") == null) {
                                map.put("newWeatherCount", 0);
                            } else {
                                map.put("newWeatherCount", weatherMaps.get("newWeatherCount"));
                            }
                        } else {
                            map.put("newWeatherCount", 0);
                        }

                        if (Integer.parseInt(map.get("newUserCount").toString()) != 0 ||
                                !map.get("newMileageCount").toString().equals("0.00") ||
                                Integer.parseInt(map.get("newWeatherCount").toString()) != 0) {

                            LogUtil.info("accountId:" + account.getAccountId() + "新用户,新里程,新气温 统计一天");
                            newUserDayStaDao.insertByMap(map);
                        }
                    }
                    newUserDayStaDao.update(account.getAccountId());
                    redisService.incr(String.valueOf(account.getAccountId()));
                }
            }

            List<MachineDaySta> machineDayStaList = machineDayStaDao.getByAccountIdDateDay(params);
            if (machineDayStaList == null || machineDayStaList.size() == 0 || !machineDayStaList.get(0).getAddTime().substring(0, 10).equals(toDay)) {

                //缺电车辆
                Integer lackPowerMachine = 0;
                List<MachineStatus> list = machineStatusService.getSocByAccountId(account.getAccountId(), account.getBorrowSocLimit());
                List<String> lackMachineNo = new LinkedList<>();
                if (list != null) {
                    lackPowerMachine = list.size();
                    for (MachineStatus machine : list) {
                        lackMachineNo.add(machine.getMachineNO());
                    }
                }

                //异常车辆
                List<MachineAbnormal> machineAbnormals = machineAbnormalService.getByAccountId(account.getAccountId());
                List<String> abnormalMachineNo = new LinkedList<>();
                if (machineAbnormals != null) {
                    for (MachineAbnormal machine : machineAbnormals) {
                        abnormalMachineNo.add(machine.getMachineNO());
                    }
                }

                //无信号车辆
                Integer lackState = 0;
                //站外的车辆
                Integer lackParkpoint = 0;

                for (MachineAbnormal machineAbnormal : machineAbnormals) {
                    if (machineAbnormal.getAbnormalType().equals(MachineAbnormalConstant.MACHINE_ABNORMAL_WXH)) {
                        lackState++;
                    } else if (machineAbnormal.getAbnormalType().equals(MachineAbnormalConstant.MACHINE_ABNORMAL_ZW)) {
                        lackParkpoint++;
                    }
                }

                //运维故障的车辆
                Integer lackFault = machineFaultService.getByAccountIdType(account.getAccountId(), 0);

                //闲置的车辆
                List<MachineStatusBorrow> machineStatusBorrows = machineStatusService.getUnUseByAccountId(account.getAccountId(), DateTimeUtil.getHoursAgo(24));
                Integer lackBorrow = machineStatusBorrows.size();

                //正在运营车辆
                Integer useMachineCount = machineService.getByAccountIdType(account.getAccountId(), MachineStateConstant.MACHINE_STATE_ZCYY);

                //可运营车辆
                Integer machineUserCount = 0;
                lackMachineNo.removeAll(abnormalMachineNo);
                lackMachineNo.addAll(abnormalMachineNo);
                machineUserCount = useMachineCount - lackMachineNo.size();

                if (machineUserCount < 0) {
                    machineUserCount = 0;
                }

                //车辆总数
                Integer countMachine = machineService.getByAccountDate(account.getAccountId(), null);

                MachineDaySta machineDaySta = new MachineDaySta();
                machineDaySta.setLackState(lackState);
                machineDaySta.setLackParkpoint(lackParkpoint);
                machineDaySta.setLackFault(lackFault);
                machineDaySta.setLackBorrow(lackBorrow);

                machineDaySta.setAccountId(account.getAccountId());
                if (machineUserCount < 0) {
                    machineDaySta.setUseMachineCount(0);
                } else {
                    machineDaySta.setUseMachineCount(machineUserCount);
                }
                machineDaySta.setLackPowerMachineCount(lackPowerMachine);
                machineDaySta.setCountMachine(countMachine);
                machineDaySta.setMachineDate(DateTimeUtil.getNowTimeYMD());

                LogUtil.info("accountId:" + account.getAccountId() + "车辆统计一天");
                machineDayStaService.insert(machineDaySta);
            }
            machineDayStaService.update(account.getAccountId());

            redisService.incr(String.valueOf(account.getAccountId()));
        }
        if (null != accounts) {
            accounts.clear();
        }
        if (null != detects) {
            detects.clear();
        }
        long t2 = System.currentTimeMillis();
        LogUtil.info("日统计定时任务时间" + (t2 - t1));
    }

    /**
     * 运营分析分时统计
     */
    @Override
    //@Scheduled(cron = "0 0 */1 * * ?")
    public void operationHourCount() {
        LogUtil.info("运营分析，分时统计" + DateTimeUtil.getNewHour());
        long t1 = System.currentTimeMillis();
        //获取所有的运营区域
        List<Account> accountList = accountService.getByType(UserConstant.ACCOUNT_AGENT);
        //获取所有运营区域异常车辆数
        List<Map<String, Object>> machineAbnormalMap = machineAbnormalService.getGroupByAccountId();
        Map<Integer, Integer> abnormalCount = new HashMap<>();
        for (int i = 0; i < machineAbnormalMap.size(); i++) {
            abnormalCount.put(Integer.parseInt(machineAbnormalMap.get(i).get("accountId").toString()), Integer.parseInt(machineAbnormalMap.get(i).get("machineIdCount").toString()));
        }

        //查看区域异常类型总数
        List<Map<String, Object>> mapAbnormalList = machineAbnormalService.getAccountIdAndType();
        Map<String, Object> mapAbnormal = new HashMap<>();
        for (Map<String, Object> map : mapAbnormalList) {
            mapAbnormal.put(map.get("accountId") + "_" + map.get("abnormalType"), map.get("machineCount"));
        }

        //查看区域故障类型总数
        List<Map<String, Object>> mapFaultList = machineFaultService.getGroupByAccountId();
        Map<String, Object> mapFault = new HashMap<>();
        for (Map<String, Object> map : mapFaultList) {
            mapFault.put(map.get("accountId") + "_" + map.get("from"), map.get("machineIdCount"));
        }

        //查看区域闲置车辆数
        List<Map<String, Object>> mapLastList = machineService.getAccountLast(DateTimeUtil.getHoursAgo(24));
        Map<String, Object> mapLast = new HashMap<>();
        for (Map<String, Object> map : mapLastList) {
            mapLast.put(map.get("accountId") + "", map.get("machineCount"));
        }

        //获取所有运营区域正在运营车辆数
        List<Map<String, Object>> machineMap = machineService.getGroupByAccountId();
        Map<Integer, Integer> machineCount = new HashMap<>();
        for (int i = 0; i < machineMap.size(); i++) {
            machineCount.put(Integer.parseInt(machineMap.get(i).get("accountId").toString()), Integer.parseInt(machineMap.get(i).get("machineIdCount").toString()));
        }

        //获取所有运营区域缺电车辆数
        List<Map<String, Object>> machineLockPowerMap = machineStatusService.getGroupByAccountIdLockPower();
        Map<Integer, Integer> machineLockPowerCount = new HashMap<>();
        for (int i = 0; i < machineLockPowerMap.size(); i++) {
            machineLockPowerCount.put(Integer.parseInt(machineLockPowerMap.get(i).get("accountId").toString()), Integer.parseInt(machineLockPowerMap.get(i).get("machineIdCount").toString()));
        }

        //获取所有运营区域在骑用户数
        List<Map<String, Object>> machineBorrowMap = machineBorrowService.getGroupByAccountId();
        Map<Integer, Integer> machineBorrowCount = new HashMap<>();
        for (int i = 0; i < machineBorrowMap.size(); i++) {
            machineBorrowCount.put(Integer.parseInt(machineBorrowMap.get(i).get("accountId").toString()), Integer.parseInt(machineBorrowMap.get(i).get("userIdCount").toString()));
        }

        for (int i = 0; i < accountList.size(); i++) {
            OperationHourSta operationHourSta = new OperationHourSta();
            operationHourSta.setAccountId(accountList.get(i).getAccountId());

            //获取在骑车辆
            Integer borrow = machineBorrowCount.get(accountList.get(i).getAccountId());
            if (borrow == null) {
                operationHourSta.setRidingMachineCount(0);
            } else {
                operationHourSta.setRidingMachineCount(borrow);
            }

            //获取缺电车辆数
            Integer lackPower = machineLockPowerCount.get(accountList.get(i).getAccountId());
            if (lackPower == null) {
                operationHourSta.setLackPowerMachineCount(0);
            } else {
                operationHourSta.setLackPowerMachineCount(lackPower);
            }

            //获取可运营车辆
            Integer useMachine = machineCount.get(accountList.get(i).getAccountId());
            if (useMachine == null || useMachine.equals(0)) {
                operationHourSta.setUseMachineCount(0);
            } else {
                Integer faultMachine = abnormalCount.get(accountList.get(i).getAccountId());
                if (faultMachine == null) {
                    operationHourSta.setUseMachineCount(useMachine);
                } else if ((useMachine - faultMachine - operationHourSta.getLackPowerMachineCount()) < 0) {
                    operationHourSta.setUseMachineCount(0);
                } else {
                    operationHourSta.setUseMachineCount(useMachine - faultMachine - operationHourSta.getLackPowerMachineCount());
                }
            }

            //无信号车辆
            Object valueState = mapAbnormal.get(accountList.get(i).getAccountId() + "_" + MachineAbnormalConstant.MACHINE_ABNORMAL_WXH);
            Integer lackState = 0;
            if (valueState != null) {
                lackState = Integer.parseInt(valueState.toString());
            }
            operationHourSta.setLackState(lackState);

            //站外的车辆
            Object valueParkPoint = mapAbnormal.get(accountList.get(i).getAccountId() + "_" + MachineAbnormalConstant.MACHINE_ABNORMAL_ZW);
            Integer lackParkpoint = 0;
            if (valueParkPoint != null) {
                lackParkpoint = Integer.parseInt(valueParkPoint.toString());
            }
            operationHourSta.setLackParkpoint(lackParkpoint);

            //运维故障的车辆
            Object valueFault = mapFault.get(accountList.get(i).getAccountId() + "_" + 0);
            Integer lackFault = 0;
            if (valueFault != null) {
                lackFault = Integer.parseInt(valueFault.toString());
            }
            operationHourSta.setLackFault(lackFault);

            //闲置的车辆
            Object valueBorrow = mapLast.get(accountList.get(i).getAccountId() + "");
            Integer lackBorrow = 0;
            if (valueBorrow != null) {
                lackBorrow = Integer.parseInt(valueBorrow.toString());
            }
            operationHourSta.setLackBorrow(lackBorrow);

            operationHourSta.setOperationHour(DateTimeUtil.getNewHour());
            operationHourSta.setAddTime(DateTimeUtil.getNowTime());

            Map map = new HashMap();
            map.put(DaoParamConstant.accountId, operationHourSta.getAccountId());
            map.put("operationHour", operationHourSta.getOperationHour());

            OperationHourSta operationHourStaDB = operationHourStaDao.getByAccountIdHour(map);
            if (operationHourStaDB != null) {
                operationHourStaDao.update(operationHourSta);
            } else {
                operationHourStaDao.insert(operationHourSta);
            }

        }
        long t2 = System.currentTimeMillis();
        LogUtil.info("分时统计，定时任务时间" + (t2 - t1));

    }

    @Override
    //@Scheduled(cron = "0 0 3 * * ?")
    public void detectAccount() {
        LogUtil.info("检测日统计，定时任务");
        long t1 = System.currentTimeMillis();

        List<Account> accountsDt = accountService.getByType(UserConstant.ACCOUNT_AGENT);
        List<AccountConfig> accountConfigList = accountConfigService.getByListAccountId(accountsDt.stream().map(Account::getAccountId).collect(Collectors.toList()));
        List<Integer> accountIdsDt = accountConfigList.stream().map(AccountConfig::getAccountId).collect(Collectors.toList());

        if (null != accountIdsDt && accountIdsDt.size() > 0) {
            Iterator<Integer> iterator = accountIdsDt.iterator();
            while (iterator.hasNext()) {
                Integer account = iterator.next();
                if ("5".equals(redisService.get(DateTimeUtil.getNowTimeYMD() + ".MAIN" + account))) {
                    LogUtil.info("检测日统计，统计完成，删除redis：" + account);
                    iterator.remove();
                }
            }
            if (!accountIdsDt.isEmpty()) {
                LogUtil.info("检测日统计，统计失败,重新统计：" + accountIdsDt);
                detects = accountIdsDt;
                operationDayCount();
            }
        }
        long t2 = System.currentTimeMillis();
        LogUtil.info("检测日统计，定时任务时间" + (t2 - t1));
    }

    @Override
    public void batchDelRedis() {
        LogUtil.info("删除缓存开始");
        String toDay = DateTimeUtil.getNowTimeYMD();
        List<Account> ids = accountService.getByType(UserConstant.ACCOUNT_AGENT);
        if (null != ids && ids.size() > 0) {
            ids.stream().forEach(account -> {
                boolean flag = redisService.exists(toDay + ".MAIN" + account.getAccountId());
                if (flag) {
                    redisService.del(toDay + ".MAIN" + account.getAccountId());
                    LogUtil.info("删除缓存" + toDay + ".MAIN" + account.getAccountId());
                } else {
                    LogUtil.info("缓存：" + toDay + ".MAIN" + account.getAccountId());
                }
            });
        }
        LogUtil.info("删除缓存结束");
    }

    /**
     * 分区日统计
     */
    @Override
    //@Scheduled(cron = "0 0 3 * * ?")
    public void geoDayCount() {
        LogUtil.info("分区日统计，定时任务");
        long t1 = System.currentTimeMillis();
        Map<String, Object> params = new HashMap<>();
        String toDay = DateTimeUtil.getNowTimeYMD();

        if (null == regionId || regionId.size() == 0) {
            //获取所有的运营区域
            regionId = georeGionService.getRegionId();
        }
        if (null == regionId) {
            return;
        }

        List<GeoreGion> geoRegions = georeGionService.getByRegionIds(regionId);
        Map<Integer, Integer> geoRegionMap = new HashMap<>();
        for (GeoreGion georeGion : geoRegions) {
            geoRegionMap.put(georeGion.getRegionId(), georeGion.getAccountId());
        }

        /**运维人员*/
        Map<Integer, Integer> accountBoundCounts = new HashMap<>();

        /**分区人员*/
        if (CollUtil.isNotEmpty(regionId)) {
            List<Map<String, Object>> regionUserCount = georeGionService.getGroupRegionId(regionId);
            for (int i = 0; i < regionUserCount.size(); i++) {
                accountBoundCounts.put(Integer.parseInt(regionUserCount.get(i).get("regionId").toString()), Integer.parseInt(regionUserCount.get(i).get("userIdCount").toString()));
            }
        }

        for (Integer region : regionId) {

            /**删除前一天的key*/
            if (redisService.get(DateTimeUtil.getDayAgo() + ".MAIN" + region + ".GEO") != null) {
                redisService.del(DateTimeUtil.getDayAgo() + ".MAIN" + region + ".GEO");
            }

            // 获取分区对应的运营区域id
            GeoreGion georeGion = georeGionService.getByRegionId(region);
            if(ObjectUtils.isNotEmpty(georeGion)){
                params.put("accountId", georeGion.getAccountId());
            }
            params.put("regionId", region);
            params.put("isCount", DateTimeUtil.getEndDateTimeBefore(-1));
            /***获取昨天的开始时间*/
            params.put("startDt", DateTimeUtil.getNowDateTimeBefore(-1) + " 00:00:00");
            /**获取今天的开始时间*/
            params.put("endDt", DateTimeUtil.getNowDateTimeBefore(0) + " 00:00:00");
            /**
             * 按天统计调度
             */
            List<DispatchDaySta> dispatchDayStaList = dispatchDayStaDao.getByRegionIdDateDay(params);
            if (dispatchDayStaList == null || dispatchDayStaList.size() == 0) {
                /**不存在数据即从按天统计到昨天*/
                List<Map<String, Object>> dispatchLogList = dispatchLogDao.getRegionIdGroupByDay(params);
                if (!dispatchLogList.isEmpty()) {
                    LogUtil.info("regionId:" + region + "调度统计所有");

                    for (Map<String, Object> map : dispatchLogList) {
                        Integer userCount = accountBoundCounts.get(region);
                        if (userCount == null || userCount == 0) {
                            map.put("meanDispatchCount", 0.00);
                        } else {
                            /**计算平均调度*/
                            BigDecimal b = new BigDecimal((float) Integer.parseInt(map.get("dispatchCount").toString()) / userCount);
                            Double result = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                            map.put("meanDispatchCount", result);
                        }
                    }

                    dispatchDayStaDao.insertRegionIdBatch(dispatchLogList);
                }
                redisService.incr(region + ".GEO");
            } else {
                /**有数据则只计算前一天*/
                DispatchDaySta dispatchDaySta = dispatchDayStaList.get(0);
                if (!dispatchDaySta.getAddTime().substring(0, 10).equals(toDay)) {
                    Map<String, Object> maps = dispatchLogDao.statRegionIdYesterdayOrder(params);
                    if (Integer.parseInt(maps.get("dispatchCount").toString()) != 0) {
                        LogUtil.info("regionId:" + region + "调度统计一天");


                        Integer userCount = accountBoundCounts.get(region);
                        if (userCount == null || userCount == 0) {
                            maps.put("meanDispatchCount", 0.00);
                        } else {
                            /**计算平均调度*/
                            BigDecimal b = new BigDecimal((float) Integer.parseInt(maps.get("dispatchCount").toString()) / userCount);
                            Double result = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                            maps.put("meanDispatchCount", result);
                        }

                        dispatchDayStaDao.insertRegionIdByMap(maps);
                    }
                    dispatchDayStaDao.updateRegionId(region);

                    redisService.incr(region + ".GEO");
                }
            }

            /**
             * 按天统计挪车*/
            List<MoveDaySta> moveDayStaList = moveDayStaDao.getByRegionIdDateDay(params);
            if (moveDayStaList == null || moveDayStaList.size() == 0) {
                /**不存在数据即从按天统计到昨天*/
                List<Map<String, Object>> moveLogList = moveLogDao.getRegionIdGroupByDay(params);
                if (!moveLogList.isEmpty()) {
                    LogUtil.info("regionId:" + region + "挪车统计所有");

                    for (Map<String, Object> map : moveLogList) {
                        Integer userCount = accountBoundCounts.get(region);
                        if (userCount == null || userCount == 0) {
                            map.put("meanMoveCount", 0.00);
                        } else {
                            /**计算平均挪车*/
                            BigDecimal b = new BigDecimal((float) Integer.parseInt(map.get("moveCount").toString()) / userCount);
                            Double result = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                            map.put("meanMoveCount", result);
                        }
                    }

                    moveDayStaDao.insertBatchRegionId(moveLogList);
                }
                redisService.incr(region + ".GEO");
            } else {
                /* *有数据则只计算前一天*/
                MoveDaySta moveDaySta = moveDayStaList.get(0);
                if (!moveDaySta.getAddTime().substring(0, 10).equals(toDay)) {
                    Map<String, Object> maps = moveLogDao.statRegionIdYesterdayOrder(params);
                    if (Integer.parseInt(maps.get("moveCount").toString()) != 0) {
                        LogUtil.info("regionId:" + region + "挪车统计一天");

                        Integer userCount = accountBoundCounts.get(region);
                        if (userCount == null || userCount == 0) {
                            maps.put("meanMoveCount", 0.00);
                        } else {
                            /**计算平均挪车*/
                            BigDecimal b = new BigDecimal((float) Integer.parseInt(maps.get("moveCount").toString()) / userCount);
                            Double result = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                            maps.put("meanMoveCount", result);
                        }

                        moveDayStaDao.insertRegionIdByMap(maps);
                    }
                    moveDayStaDao.updateRegionId(region);
                    redisService.incr(region + ".GEO");
                }
            }

            /**
             * 按天统计换电*/
            List<PowerDaySta> powerDayStaList = powerDayStaDao.getByRegionIdDateDay(params);
            if (powerDayStaList == null || powerDayStaList.size() == 0) {
                /**不存在数据即从按天统计到昨天*/
                List<Map<String, Object>> powerLogList = powerChangeLogDao.getRegionIdGroupByDay(params);
                if (!powerLogList.isEmpty()) {
                    LogUtil.info("regionId:" + region + "换电统计所有");

                    for (Map<String, Object> map : powerLogList) {
                        Integer userCount = accountBoundCounts.get(region);
                        if (userCount == null || userCount == 0) {
                            map.put("meanPowerCount", 0.00);
                        } else {
                            /**计算平均换电*/
                            BigDecimal b = new BigDecimal((float) Integer.parseInt(map.get("powerCount").toString()) / userCount);
                            Double result = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                            map.put("meanPowerCount", result);
                        }
                    }

                    powerDayStaDao.insertRegionIdBatch(powerLogList);
                }
                redisService.incr(region + ".GEO");
            } else {
                /**有数据则只计算前一天*/
                PowerDaySta powerDaySta = powerDayStaList.get(0);
                if (!powerDaySta.getAddTime().substring(0, 10).equals(toDay)) {
                    Map<String, Object> maps = powerChangeLogDao.statRegionIdYesterdayOrder(params);
                    if (Integer.parseInt(maps.get("powerCount").toString()) != 0) {
                        LogUtil.info("regionId:" + region + "换电统计一天");

                        Integer userCount = accountBoundCounts.get(region);
                        if (userCount == null || userCount == 0) {
                            maps.put("meanPowerCount", 0.00);
                        } else {
                            /**计算平均换电*/
                            BigDecimal b = new BigDecimal((float) Integer.parseInt(maps.get("powerCount").toString()) / userCount);
                            Double result = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                            maps.put("meanPowerCount", result);
                        }

                        powerDayStaDao.insertRegionIdByMap(maps);
                    }
                    powerDayStaDao.updateRegionId(region);
                    redisService.incr(region + ".GEO");
                }
            }


            List<MachineDaySta> machineDayStaList = machineDayStaDao.getByRegionIdDateDay(params);
            if (machineDayStaList == null || machineDayStaList.size() == 0 || !machineDayStaList.get(0).getAddTime().substring(0, 10).equals(toDay)) {

                List<Integer> regions = new LinkedList<>();
                regions.add(region);

                /**车辆总数*/
                List<Map<String, Object>> countList = georeMachineService.getMachine(regions);
                Map<Integer, Integer> countMap = new HashMap<>();
                for (Map<String, Object> mapCount : countList) {
                    countMap.put(Integer.parseInt(mapCount.get("regionId").toString()), Integer.parseInt(mapCount.get("machineCount").toString()));
                }

                /**正在骑行车辆数*/
                List<Map<String, Object>> machineUseIng = machineBorrowService.getGroupByRegionId(regions);
                Map<Integer, Integer> useMap = new HashMap<>();
                for (Map<String, Object> mapCount : machineUseIng) {
                    useMap.put(Integer.parseInt(mapCount.get("regionId").toString()), Integer.parseInt(mapCount.get("useMachine").toString()));
                }

                /**流入车辆*/
                List<Map<String, Object>> intoList = georeMachineService.intoMachine(regions);
                Map<Integer, Integer> intoMap = new HashMap<>();
                for (Map<String, Object> mapInto : intoList) {
                    intoMap.put(Integer.parseInt(mapInto.get("regionId").toString()), Integer.parseInt(mapInto.get("machineCount").toString()));
                }

                /**流出车辆*/
                List<Map<String, Object>> outList = georeMachineService.outMachine(regions);
                Map<Integer, Integer> outMap = new HashMap<>();
                for (Map<String, Object> mapOut : outList) {
                    outMap.put(Integer.parseInt(mapOut.get("beforeRegionId").toString()), Integer.parseInt(mapOut.get("machineCount").toString()));
                }

                /**故障车辆*/
                List<Map<String, Object>> faultList = georeMachineService.getFault(regions);
                Map<Integer, Integer> faultMap = new HashMap<>();
                for (Map<String, Object> mapFault : faultList) {
                    faultMap.put(Integer.parseInt(mapFault.get("regionId").toString()), Integer.parseInt(mapFault.get("machineCount").toString()));
                }

                /**闲置车辆*/
                List<Map<String, Object>> borrowList = georeMachineService.getBorrow(regions);
                Map<Integer, Integer> borrowMap = new HashMap<>();
                for (Map<String, Object> mapBorrow : borrowList) {
                    borrowMap.put(Integer.parseInt(mapBorrow.get("regionId").toString()), Integer.parseInt(mapBorrow.get("machineCount").toString()));
                }

                /**缺电车辆*/
                List<Map<String, Object>> powerList = georeMachineService.getPower(regions, geoRegionMap.get(region));
                Map<Integer, Integer> powerMap = new HashMap<>();
                for (Map<String, Object> mapPower : powerList) {
                    powerMap.put(Integer.parseInt(mapPower.get("regionId").toString()), Integer.parseInt(mapPower.get("machineCount").toString()));
                }

                /**异常车辆*/
                List<Map<String, Object>> abnormalList = georeMachineService.getAbnormal(regions);
                Map<String, Integer> abnormalMap = new HashMap<>();
                for (Map<String, Object> mapAbnormal : abnormalList) {
                    abnormalMap.put(mapAbnormal.get("regionId") + "_" + mapAbnormal.get("abnormalType"), Integer.parseInt(mapAbnormal.get("machineCount").toString()));
                }

                MachineDaySta machineDaySta = new MachineDaySta();
                machineDaySta.setRegionId(region);
                /**车辆总数*/
                if (countMap.containsKey(region)) {
                    machineDaySta.setCountMachine(countMap.get(region));
                } else {
                    machineDaySta.setCountMachine(0);
                }
                /**正在骑行*/
                if (useMap.containsKey(region)) {
                    machineDaySta.setRiding(useMap.get(region));
                } else {
                    machineDaySta.setRiding(0);
                }
                /**流入*/
                if (intoMap.containsKey(region)) {
                    machineDaySta.setIntoMachine(intoMap.get(region));
                } else {
                    machineDaySta.setIntoMachine(0);
                }
                /**流出*/
                if (outMap.containsKey(region)) {
                    machineDaySta.setOutMachine(outMap.get(region));
                } else {
                    machineDaySta.setOutMachine(0);
                }
                /**故障*/
                if (faultMap.containsKey(region)) {
                    machineDaySta.setLackFault(faultMap.get(region));
                } else {
                    machineDaySta.setLackFault(0);
                }
                /**闲置*/
                if (borrowMap.containsKey(region)) {
                    machineDaySta.setLackBorrow(borrowMap.get(region));
                } else {
                    machineDaySta.setLackBorrow(0);
                }
                /**缺电*/
                if (powerMap.containsKey(region)) {
                    machineDaySta.setLackPowerMachineCount(powerMap.get(region));
                } else {
                    machineDaySta.setLackPowerMachineCount(0);
                }
                /**超区*/
                if (abnormalMap.containsKey(region + "_" + MachineAbnormalConstant.MACHINE_ABNORMAL_CCQY)) {
                    machineDaySta.setLackSuper(abnormalMap.get(region + "_" + MachineAbnormalConstant.MACHINE_ABNORMAL_CCQY));
                } else {
                    machineDaySta.setLackSuper(0);
                }
                /**站外*/
                if (abnormalMap.containsKey(region + "_" + MachineAbnormalConstant.MACHINE_ABNORMAL_ZW)) {
                    machineDaySta.setLackParkpoint(abnormalMap.get(region + "_" + MachineAbnormalConstant.MACHINE_ABNORMAL_ZW));
                } else {
                    machineDaySta.setLackParkpoint(0);
                }
                /**无信号*/
                if (abnormalMap.containsKey(region + "_" + MachineAbnormalConstant.MACHINE_ABNORMAL_WXH)) {
                    machineDaySta.setLackState(abnormalMap.get(region + "_" + MachineAbnormalConstant.MACHINE_ABNORMAL_WXH));
                } else {
                    machineDaySta.setLackState(0);
                }
                /**电池异常*/
                if (abnormalMap.containsKey(region + "_" + MachineAbnormalConstant.MACHINE_ABNORMAL_DCYC)) {
                    machineDaySta.setLackBattery(abnormalMap.get(region + "_" + MachineAbnormalConstant.MACHINE_ABNORMAL_DCYC));
                } else {
                    machineDaySta.setLackBattery(0);
                }
                /**禁停区异常*/
                if (abnormalMap.containsKey(region + "_" + MachineAbnormalConstant.MACHINE_ABNORMAL_JTYC)) {
                    machineDaySta.setLackArea(abnormalMap.get(region + "_" + MachineAbnormalConstant.MACHINE_ABNORMAL_JTYC));
                } else {
                    machineDaySta.setLackArea(0);
                }
                /**可运营车辆数*/
                Integer useCount = machineDaySta.getCountMachine() - machineDaySta.getLackFault() - machineDaySta.getLackPowerMachineCount() -
                        machineDaySta.getLackParkpoint() - machineDaySta.getLackState() - machineDaySta.getLackSuper() - machineDaySta.getLackBattery() -
                        machineDaySta.getLackArea();
                if (useCount < 0) {
                    machineDaySta.setUseMachineCount(0);
                } else {
                    machineDaySta.setUseMachineCount(useCount);
                }
                machineDaySta.setMachineDate(DateTimeUtil.getNowTimeYMD());

                LogUtil.info("region:" + region + "车辆统计一天");
                machineDayStaService.insertRegionId(machineDaySta);
            }
            machineDayStaService.updateRegionId(region);

            redisService.incr(region + ".GEO");
        }

        if (null != regionId) {
            regionId.clear();
        }
        long t2 = System.currentTimeMillis();
        LogUtil.info("分区日统计定时任务时间" + (t2 - t1));
    }

    @Override
    //@Scheduled(cron = "0 30 3 * * ?")
    public void detectGeoRegion() {
        LogUtil.info("检测日分区统计，定时任务");
        long t1 = System.currentTimeMillis();

        List<Integer> regionIdsDt = georeGionService.getRegionId();
        if (null != regionIdsDt && regionIdsDt.size() > 0) {
            Iterator<Integer> iterator = regionIdsDt.iterator();
            while (iterator.hasNext()) {
                Integer region = iterator.next();
                if ("4".equals(redisService.get(DateTimeUtil.getNowTimeYMD() + ".MAIN" + region + ".GEO"))) {
                    LogUtil.info("检测分区日统计，统计完成，删除redis，regionId：" + region);
                    iterator.remove();
                }
            }
            if (!regionIdsDt.isEmpty()) {
                LogUtil.info("检测日统计，统计失败,重新统计,regionId：" + regionIdsDt);
                regionId = regionIdsDt;
                geoDayCount();
            }
        }

        long t2 = System.currentTimeMillis();
        LogUtil.info("检测日分区统计，定时任务时间" + (t2 - t1));
    }

    @Override
    public void batchRegionDelRedis() {
        LogUtil.info("删除region缓存开始");
        String toDay = DateTimeUtil.getNowTimeYMD();
        List<Integer> ids = georeGionService.getRegionId();
        if (null != ids && ids.size() > 0) {
            ids.stream().forEach(regionId -> {
                boolean flag = redisService.exists(toDay + ".MAIN" + regionId + ".GEO");
                if (flag) {
                    redisService.del(toDay + ".MAIN" + regionId + ".GEO");
                    LogUtil.info("删除region缓存" + toDay + ".MAIN" + regionId + ".GEO");
                } else {
                    LogUtil.info("region缓存：" + toDay + ".MAIN" + regionId + ".GEO");
                }
            });
        }
        LogUtil.info("删除region缓存结束");
    }
}
